package org.rency.ues.annotation.service.impl;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.rency.ues.annotation.service.DecryptService;
import org.rency.ues.annotation.support.AnnotationUtils;
import org.rency.ues.annotation.support.AnnotionData;
import org.rency.ues.client.UesClient;
import org.rency.ues.common.UesException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author: Created by user_rcy@163.com on 2016/8/3.
 */
public class DecryptServiceImpl implements DecryptService {

    private static final Logger logger = LoggerFactory.getLogger(DecryptServiceImpl.class);

    private UesClient uesClient;

    @Override
    public Object process(Object param, AnnotionData data) throws Exception {
        if(AnnotationUtils.isEmptyObject(param) || data == null){
            return null;
        }
        List<String> includeFields = data.getIncludeFields();
        if(CollectionUtils.isEmpty(includeFields)){
            logger.warn("decrypt field collection is empty.");
            return param;
        }
        if(AnnotationUtils.isCollection(param)){
            if (param.getClass().isArray()) {
                Object[] arr = (Object[]) param;
                for (int i = 0; i < arr.length; i++) {
                    decryptObject(arr[i], includeFields);
                }
            } else {
                Collection<?> col = (Collection<?>) param;
                Iterator<?> it = col.iterator();
                Object item = null;
                while (it.hasNext()) {
                    item = it.next();
                    decryptObject(item, includeFields);
                }
            }
        }else{
            decryptObject(param, includeFields);
        }
        return param;
    }

    private Object decryptObject(Object arg, List<String> fields) throws Exception {
        Map<String, String> valueCarrier = new HashMap<String, String>();
        List<String> ticketList = new ArrayList<String>();
        for(String fieldName : fields){
            Object value = AnnotationUtils.getFieldValue(arg, fieldName);
            if(value instanceof String){
                String ticket = (String) value;
                valueCarrier.put(fieldName,ticket);
                ticketList.add(ticket);
            }
        }
        if(CollectionUtils.isEmpty(ticketList)){
            return arg;
        }
        Map<String, String> plainDataMap = uesClient.decrypt(ticketList);
        if(MapUtils.isEmpty(plainDataMap)){
            throw new UesException("注解远程解密失败.");
        }
        for(String fieldName : fields){
            String ticket = valueCarrier.get(fieldName);
            String plainData = plainDataMap.get(ticket);
            AnnotationUtils.setFieldValue(arg,fieldName,plainData);
        }
        return arg;
    }

    public void setUesClient(UesClient uesClient) {
        this.uesClient = uesClient;
    }
}
